package campus.evip.server.servlets;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.cocoon.servlet.multipart.MultipartHttpServletRequest;

import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.MultipartParser;



@SuppressWarnings("serial")
public class XSLTTestSuiteServlet extends HttpServlet {
    private File baseDir = null;
    private Transformer transformer = null, htmlTransformer = null;

	public void init (ServletConfig config) throws ServletException {
	   super.init (config);	  	  
	   
	   if (config.getInitParameter ("basedir") != null)
		  try {
			  doInit (new File (config.getInitParameter ("basedir")));
		      } catch (Exception ex) { throw new ServletException (ex); }
	   }
	
	private void doInit (File aBaseDir) throws Exception {
	   this.baseDir = aBaseDir;

       URIResolver uriResolver = new URIResolver () {
	       public Source resolve (String href, String base) throws TransformerException {
	    	    return new StreamSource (new File (/*baseDir, base == null ? "" : base+"/")+*/href));
	    	    }
	         };
	   TransformerFactory transformerFactory = TransformerFactory.newInstance ();
	   transformerFactory.setURIResolver (uriResolver);
	   transformer = transformerFactory.newTransformer (new StreamSource (new File (baseDir, "test-suite.xslt")));	   
	   transformer.setParameter ("schemas-basedir", baseDir.getAbsolutePath ());
	   htmlTransformer = transformerFactory.newTransformer (new StreamSource (new File (baseDir, "format/test-result.xslt")));
	   }
	
	protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	   response.setContentType ("text/html");
	   PrintWriter pw = response.getWriter ();
	   pw.println ("<html><head><title>XSLT-Testsuite-Upload</title></head><body>");
	   pw.println ("<form method=\"post\" enctype=\"multipart/form-data\">");
	   pw.println ("ZIP-File: ");
	   pw.println ("<input name=\"zip\" type=\"file\"/>");
	   pw.println ("<select name=\"format\"><option>XML</option><option>HTML</option>");
	   pw.println("<input type=\"submit\"/>");
	   pw.println("</form></body></html>");
  	   }

	protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	   MultipartRequest mRequest = new MultipartRequest (request, System.getProperty ("java.io.tmpdir"), Integer.MAX_VALUE);

	   File tmpFile = new File (new File (System.getProperty ("java.io.tmpdir")), "zip-extract-"+Math.random ());
	   tmpFile.mkdir ();
	   tmpFile.deleteOnExit ();
	   try {
		   if (baseDir == null)
			  synchronized (this) {
				if (baseDir == null)
				   doInit (new File (getServletContext ().getRealPath ("/")));
			    }
		   
	       ZipInputStream zip = new ZipInputStream (new FileInputStream (mRequest.getFile ("zip")));
	       extractZIP (zip, tmpFile);
	       zip.close ();
	       
	       transformer.setParameter ("basedir", tmpFile.getAbsolutePath ());
	       
	       ByteArrayOutputStream baos = new ByteArrayOutputStream ();
	       transformer.transform (new StreamSource (new StringReader ("<?xml version=\"1.0\"?><empty></empty>")), new StreamResult (baos));
	       
	       if ("html".equalsIgnoreCase (mRequest.getParameter ("format"))) {
	    	  response.setContentType ("text/html");
	    	  htmlTransformer.transform (new StreamSource (new ByteArrayInputStream (baos.toByteArray ())), new StreamResult (response.getOutputStream ())); 
	          } else {
	        	     response.setContentType ("text/xml");
	        	     response.getOutputStream ().write (baos.toByteArray ());
	                 }	       
	       } catch (Exception ex) { throw new ServletException (ex); }
	   
	   }
	
	
	private static void extractZIP (ZipInputStream in, File tmpFile) throws IOException {
	   ZipEntry entry;
	   while ((entry = in.getNextEntry ()) != null) {
		     //File newFile = new File (dir, entry.getName ().replace ('\\', '/'));
		     if (entry.isDirectory ()) continue;

			 String[] dirs = entry.getName ().replace ('\\', '/').split ("/");
			 File dir = tmpFile;
			 for (int i = 0; i < dirs.length - 1; i++) {
			 	 dir = new File (dir, dirs[i]);
				 dir.mkdir ();
				 dir.deleteOnExit ();
				 }
			 File file = new File (dir, dirs[dirs.length - 1]);
			 file.deleteOnExit ();
			 copy (in, file);
			 file.deleteOnExit ();
	         }
	   }
	
	private static void copy (InputStream in, File file) throws IOException {
	   byte[] bytes = new byte[4096];
	   int available;
	   FileOutputStream out = new FileOutputStream (file);
	   while ((available = in.read (bytes)) > 0)
		     out.write (bytes, 0, available);
	   out.close ();
	   }

}
